#Responsability:
#Prepare de parameters for the Ldndc model
library("lhs")
require("MASS")

ParametersGenerator <- setRefClass(    
  "parametersgenerator"
  , fields = list(
      parameterDistribution="data.frame",
      firstParameter="data.frame",
      covarianceMatrix="matrix"
    )
  , methods = list(
    initialize = function(...) {
      
      
      callSuper(...)
      firstParameters()
      
    },
    firstParameters = function() {
      
      .self$firstParameter <<- data.frame(parameterDistribution$init ,row.names=parameterDistribution$name)
      
      min <- parameterDistribution$min
      max <- parameterDistribution$max
      
      #print(.self$firstParameter)
      lhs_matrix <- optimumLHS(n=1,k=nrow(.self$firstParameter))
      
      # move random number from (0,1) to given intervall
      .self$firstParameter[,1] <<- lhs_matrix[1,] * (max - min ) + min 
    
      #TODO: I have no clear the value of stepWidth
      stepWidth <- 1
      .self$covarianceMatrix <<- diag((stepWidth * (max-min))^2)
    },
    #
    #
    # Generate new set of parameters for the model
    #
    #
    newRandomParameters = function(parameter) {
      
        print("METHOD IN: selectStartingPointInParameterSpace")
        
        # mvrnorm -> Multivariate normal distribution
        if (is.null(parameter) || (length(parameter) == 0))
          parameter <- firstParameter
        
        min <- parameterDistribution$min
        max <- parameterDistribution$max
        
        #parameter is the table with the lasta accepted parameters
        #covProposal es la matriz covarianza para obtener los nuevos parametros
        cand <- mvrnorm(n=1,parameter[,1], covarianceMatrix)
        
        # bounce if cand not in parameter space 
        # if Cand is out of boundarys bounce into boundarys (shouldnt be done with normal dist)
        # if Cand is TOO small or TOO large bounce to maximum or to minimum value respectively 
        outofbounds <- which(cand < min  & ( min - cand < max - min) ) 
        cand[ outofbounds ] <- (min[outofbounds] - cand[outofbounds] ) + min[outofbounds]
        
        outofbounds <- which(cand < min  & ( min - cand >= max - min) )
        cand[ outofbounds ] <-  max[outofbounds]
        
        outofbounds <- which(cand > max  & ( cand - max < max - min) )
        cand[ outofbounds ] <- (max[outofbounds] - cand[outofbounds] ) + max[outofbounds]
        
        outofbounds <- which(cand > max  & ( cand - max >= max - min) )
        cand[ outofbounds ] <- min[outofbounds] 
        
        print("METHOD OUT: selectStartingPointInParameterSpace")
        
        # show(cand)
        
        #cand doesn't have the column names
        parameter[,1] <- cand
        
        parameter
    }
    
                                
    )#End methods List 
  
)#End RefClass
